`timescale 1ns/1ns
module L9_data_rec_02(
		input	wire		resetb,
		input	wire		sclk,
		
		//设置总线
	        input	wire		set_d_ok,
	        input	wire	[15:0]	set_addr,
	        input	wire	[7:0]	set_data,
	        
		//模式控制
		input   wire            init_mode,
		input   wire            black,

		//开机渐亮控制
		input   wire            test_vs,
		input   wire            local_test_en,
		input   wire            local_picture_en,
		
		//多模块共用设置数据输出
		output  reg	[10:0]  h_total,
		output  reg	[10:0]  l_total,
		output	reg	[7:0]	no_vs_set,	
                output  reg     [7:0]   local_depth,
                output	reg		local_depth_en,
                output	reg		cas_depth_adj,
                output  reg     [23:0]  local_net,
                output	reg		local_net_en,
                
		//网口数据输入
		input	wire		mac_flag,
		input	wire	[7:0]	mac_data,
		input	wire	[1:0]	mac_vendor,//0:无效包 1：中庆UDP 2：YT 3:中庆长包
		input	wire		mac_error,
		
		//显示数据输出
		output	reg		vsout,
		output	reg		dsout,
		output	wire	[7:0]	dout,
		output	reg		h_start,
		output	reg	[10:0]	h_num,
		output	reg		l2048_mode,
		
		//显示设置数据输出
		output	reg	[7:0]	state,
		output	reg	[7:0]	state_2,
		output	reg	[1:0]	color_restore_type,
		output	reg	[7:0]	testmode,
		output	reg	[63:0]	unit_color_adj,
		output  reg     [8:0]   cascade_light,
		output	reg	[7:0]	led_light,
		
		//测试信号
		output	wire	[7:0]	tout
		);

/************************************************/
//		信号定义
/************************************************/
parameter  Preamble_OFFSET	= 51;
parameter  PACK_TYPE_FIRST	= 52 - Preamble_OFFSET;
parameter  PACK_DEPTH_FIRST	= 56 - Preamble_OFFSET;
parameter  HPACK_ADDR_START	= 58 - Preamble_OFFSET;
parameter  PACK_LENGTH_HIGH	= 63 - Preamble_OFFSET;
parameter  PACK_DATA_START	= 64 - Preamble_OFFSET;
parameter  SET_PACK_OFFSET	= PACK_DATA_START-2;

reg	[12:0]	h_offset_bin,l_offset_bin,h_total_bin,l_total_bin;
reg	[5:0]	display_num;
reg	[1:0]	pixel_mode;
reg		light_on_protect,auto_display_pos,local_depth_en_t;
reg	[8:0]	unit_r_adj,unit_g_adj,unit_b_adj,unit_w_adj;
wire		color_restore_receiver;

reg	[10:0]	mac_count,set_count;
reg	[9:0]	current_depth_t,current_depth_c,current_depth;
reg	[7:0]	r_light,g_light,b_light;
reg	[12:0]	h_offset,l_offset,h_end,l_end;
reg	[14:0]	d_offset,d_end;
reg		zdec_vsout,set_en_pre,data_en_pre,set_en;
reg	[3:0]	set_count_t;
reg	[12:0]	h_num_rec,h_count;
reg	[14:0]	d_num_rec,d_end_rec,h_d_max,d_count;
reg		d_flag;

reg	[6:0]	contrast_da;
reg		flag_da,flag_db;
reg	[7:0]	contrast_adj,contrast_d;
wire	[17:0]	contrast_db;
reg     [7:0]   start_light;
wire	[17:0]	sys_adj_result;
wire	[31:0]	adj_result_r,adj_result_g,adj_result_b,adj_result_w;
wire	[15:0]	r_adj_out,g_adj_out,b_adj_out,w_adj_out;
reg		test_vs_r,local_vs_negedge;

reg		d_start,dsout_t,h_start_t;
reg		end_flag,end_flag_t;

/************************************************/
//		参数设置
/************************************************/
always	@(posedge sclk or negedge resetb)
	if (resetb==0)
		begin
			h_offset_bin	<= 0;
			l_offset_bin	<= 0;
			h_total_bin	<= 8;
			l_total_bin	<= 1024;
			display_num	<= 0;
			pixel_mode	<= 0;
			no_vs_set	<= 0;
			light_on_protect<= 1;
			auto_display_pos<= 0;
			unit_r_adj	<= 9'h100;
			unit_g_adj	<= 9'h100;
			unit_b_adj	<= 9'h100;
			unit_w_adj	<= 9'h100;
			color_restore_type<= 2'b00;
			local_depth	<= 0;
			local_depth_en_t<= 0;
			cas_depth_adj	<= 0;
			local_net	<= 0;
			local_net_en	<= 0;
		end
	else if (set_d_ok==1)
		case (set_addr)
			16'h0100:	h_offset_bin[7:0]	<= set_data;
			16'h0101:	h_offset_bin[12:8]	<= set_data;
			16'h0102:	l_offset_bin[7:0]	<= set_data;
			16'h0103:	l_offset_bin[12:8]	<= set_data;
			16'h0104:	h_total_bin[7:0]	<= set_data;
			16'h0105:	h_total_bin[12:8]	<= set_data;          
			16'h0106:	l_total_bin[7:0]	<= set_data;
			16'h0107:	l_total_bin[12:8]	<= set_data;  
			16'h0108:	begin
			                if(set_data == 0)                 //与未加多屏功能的配置文件保持兼容
			                        display_num <= 0; 	
			                else 
			                	display_num <= set_data - 1;
			                end		     
			16'h0209:	local_depth <= set_data;  
			16'h020a:	begin
			                if(set_data == 8'h3C)                 //与未加多屏功能的配置文件保持兼容
			                        local_depth_en_t <= 1; 	
			                else 
			                	local_depth_en_t <= 0;
			                end		     
			16'h020b:	begin
			                if(set_data == 8'h3C)                 //与未加多屏功能的配置文件保持兼容
			                        cas_depth_adj <= 1; 	
			                else 
			                	cas_depth_adj <= 0;
			                end		     
			16'h0210:	begin
			                if(set_data == 8'h3C)                 //与未加多屏功能的配置文件保持兼容
			                        local_net_en <= 1; 	
			                else 
			                	local_net_en <= 0;
			                end		     
			16'h0211:	local_net[23:16]	<= set_data;  
			16'h0212:	local_net[15:8]		<= set_data;  
			16'h0213:	local_net[7:0]		<= set_data;  
			16'h1032:	color_restore_type<=set_data[1:0];
			16'h1040:	pixel_mode<=set_data[1:0];
			16'h1050:	no_vs_set<=set_data;
			16'h1053:	light_on_protect<=set_data[0];
			
			16'h1099:	auto_display_pos<=set_data[0];	//L9使用，位置自适应使能
			
			16'h7000:	unit_r_adj <= set_data + 1;
			16'h7001:	unit_g_adj <= set_data + 1;
			16'h7002:	unit_b_adj <= set_data + 1;
			16'h7003:	unit_w_adj <= set_data + 1;		
		endcase

always	@(posedge sclk)
	if (cas_depth_adj == 1)
		local_depth_en <= 1;
	else
		local_depth_en <= local_depth_en_t;

assign  color_restore_receiver = color_restore_type[1];
/************************************************/
//		数据包内字节计数
/************************************************/
always	@(posedge sclk)
	if (mac_flag==0)
		mac_count<=0;
	else if (mac_count[10]==0)
		mac_count<=mac_count+1;
						
/************************************************/
//		自适应截取处理
/************************************************/
//从数据包中提取级联深度数据
always	@(posedge sclk or negedge resetb)
	if(resetb==0)
		current_depth_t <=2;
	else if (data_en_pre == 1 && mac_count == PACK_DEPTH_FIRST)
		current_depth_t[7:0] <= mac_data;
	else if (data_en_pre == 1 && mac_count == PACK_DEPTH_FIRST + 1)
		current_depth_t[9:8] <= mac_data;
		
//在数据包校验正确时应用级联深度数据
always	@(posedge sclk or negedge resetb)
	if(resetb == 0)
		current_depth_c <= 0;
	else if(mac_flag == 0 && mac_error == 0)
		current_depth_c <= current_depth_t;
	
//选择级联深度来源：本地保存/通讯接口提取
always	@(posedge sclk)
	if(local_depth_en == 0)
		current_depth <= current_depth_c - 1;
	else
		current_depth <= local_depth - 1;

//选择自动确定截取位置/本地固化的街区位置
always	@(posedge sclk)
	if(auto_display_pos==1)
	begin
		h_offset	<= {current_depth[9:0],3'b000};
		l_offset	<= 0;
		h_total		<= 16;
		l_total		<= 1024;
	end
	else
	begin
		h_offset	<=h_offset_bin;
		l_offset	<=l_offset_bin;
		h_total		<=h_total_bin;
		l_total		<=l_total_bin;	
	end

always	@(posedge sclk)
	if (l_total > 1024)
		l2048_mode <= 1;
	else
		l2048_mode <= 0;
		
//行截取范围
always	@(posedge sclk)
	h_end <= h_offset + h_total;

//行内数据截取范围
always	@(posedge sclk)
	l_end <= l_offset + l_total;	

always@(posedge sclk)
	begin
		d_offset <= {l_offset[10:0],1'b0} + l_offset;
		d_end <= {l_end[10:0],1'b0} + l_end;
	end

/************************************************/
//		帧包处理
/************************************************/
always	@(posedge sclk)
	if (mac_flag==0)
		zdec_vsout<=0;
	else if (mac_count==PACK_TYPE_FIRST && mac_data==8'hFA && (mac_vendor==1 || mac_vendor==3))
		zdec_vsout<=1;

/************************************************/
//		即时显示设置参数提取
/************************************************/
//显示设置包标志
always	@(posedge sclk)
	if (mac_flag==0)
		set_en_pre<=0;
	else if (mac_count==PACK_TYPE_FIRST && mac_data==8'hF0 && (mac_vendor==1 || mac_vendor==3))
		set_en_pre<=1;

//设置数据计数
always@(posedge sclk)
	set_count<=mac_count-SET_PACK_OFFSET;

//判断是否是本显示屏数据
always@(posedge sclk)
        if(set_count[10:4]==display_num)
                set_en<=1'b1;
        else
                set_en<=1'b0;

always@(posedge sclk)
        set_count_t<=set_count[3:0];

//设置数据提取                
always	@(posedge sclk or negedge resetb)
	if (resetb==0)
		begin
			state		<=64;
			state_2		<=0;
			contrast_adj	<=64;
			led_light<='hff;
			r_light<='h0100;
			g_light<='h0100;
			b_light<='h0100;
		end
	else if (set_en_pre==1 && set_en==1) begin
		case (set_count_t[3:0])
			0:	state		<=mac_data;
			1:	state_2		<=mac_data;
			3:	begin
			        if (mac_data!=0) 
					contrast_adj	<=mac_data;
				else
				        contrast_adj    <=64;        
				end
			4:	led_light<=mac_data;
			5:	r_light<=mac_data+1;
			6:	g_light<=mac_data+1;
			7:	b_light<=mac_data+1;
			15:	testmode<=mac_data;
		endcase
	end
	
/************************************************/
//	显示数据包解析本地行号，总列号计算
/************************************************/
//显示设置包标志
always	@(posedge sclk)
	if (mac_flag==0)
		data_en_pre<=0;
	else if (mac_count==PACK_TYPE_FIRST && mac_data==8'hF5 && (mac_vendor==1 || mac_vendor==3))	//UDP
		data_en_pre<=1;
		
//起始行号，数据偏移量，每行数据长度
always	@(posedge sclk or negedge resetb)
	if(!resetb)
	begin
		h_num_rec<=0;
		d_num_rec<=0;
		d_end_rec<=0;
	end
	else if (data_en_pre==1)
		case (mac_count)
			HPACK_ADDR_START:	h_num_rec[7:0]<=mac_data;
			HPACK_ADDR_START+1:	h_num_rec[12:8]<=mac_data;
			HPACK_ADDR_START+2:	d_num_rec[7:0]<=mac_data;
			HPACK_ADDR_START+3:	d_num_rec[14:8]<=mac_data;
			HPACK_ADDR_START+4:	d_end_rec[7:0]<=mac_data;
			HPACK_ADDR_START+5:	d_end_rec[14:8]<=mac_data;
		endcase

always@(posedge sclk)
	h_d_max <= d_end_rec - 1;

/************************************************/
//		本地输出
/************************************************/
//数据有效标志
always	@(posedge sclk)
	if (data_en_pre == 1 && mac_count == PACK_LENGTH_HIGH)
		d_start <= 1;
	else
		d_start <= 0;

always	@(posedge sclk)
	if (mac_flag==0)
		d_flag <= 0;
	else if (data_en_pre==1 && d_start == 1)
		d_flag <= 1;

//行内数据计数
always	@(posedge sclk)
	if(zdec_vsout == 1)
		d_count <= 0;
	else if (d_flag == 1 && d_count >= h_d_max)
		d_count <= 0;
	else if (d_start == 1)
		d_count <= d_num_rec;
	else if (d_flag == 1)
		d_count <= d_count + 1;
				
//行号计算
always@(posedge sclk)
	if(zdec_vsout == 1)
		h_count <= 0;
	else if (d_flag == 1 && d_count >= h_d_max)
		h_count <= h_count + 1;
	else if (d_start == 1)
		h_count <= h_num_rec;
		
always@(posedge sclk)
	if(d_flag == 0)
		dsout_t <= 0;
	else if (h_count < h_offset || h_count >= h_end)
		dsout_t <= 0;
	else if (d_count < d_offset || d_count >= d_end)
		dsout_t <= 0;
	else
		dsout_t <= 1;

always@(posedge sclk)
	if(d_flag == 0)
		h_start_t <= 0;
	else if (h_count < h_offset || h_count >= h_end)
		h_start_t <= 0;
	else if (d_count == d_offset)
		h_start_t <= 1;
	else
		h_start_t <= 0;

always@(posedge sclk)
	if(vsout == 1)
		end_flag <= 0;
	else if (h_count >= h_end)
		end_flag <= 1;

always@(posedge sclk)
	end_flag_t <= end_flag;

always@(posedge sclk)
	dsout <= dsout_t;

assign	dout = contrast_d;

always@(posedge sclk)
	vsout <= zdec_vsout;

always@(posedge sclk)
	if (h_start_t == 1)
		h_start <= 1;
	else if (end_flag_t == 0 && end_flag == 1)
		h_start <= 1;
	else
		h_start <= 0;

always@(posedge sclk)
	h_num <= h_count - h_offset;

/************************************************/
//		对比度调整
/************************************************/
always	@(posedge sclk)
	if (mac_data[7]==1)
		contrast_da<=mac_data[6:0];
	else
		contrast_da<=~mac_data[6:0];

always	@(posedge sclk) begin
	flag_da<=mac_data[7];
	flag_db<=flag_da;
	end
	           
mult_9X9_sync	adjust_contrast (
	.clock ( sclk ),
	.dataa ( {1'b0,contrast_adj} ),
	.datab ( {2'h0,contrast_da} ),
	.result ( contrast_db )
	);

always	@(posedge sclk)
	if (dsout_t == 0)
		contrast_d <= 0;
	else if (flag_db==1) begin
		if (contrast_db[14:13]>0)
			contrast_d<=8'hff;
		else
			contrast_d<={1'b1,contrast_db[12:6]};
		end
	else if (contrast_db[14:13]>0)
		contrast_d<=8'h0;
	else
		contrast_d<={1'b0,~contrast_db[12:6]};

//************************************************
//		亮度调整处理
//************************************************
//*****************软件设置亮度及开屏亮度数据***************	
always	@(posedge sclk)
        if(init_mode==1'b1)
                cascade_light<=9'h100;
	else if (set_en_pre==1 && set_en==1 && set_count_t[3:0]==4'b0100) begin
	        if(mac_data==0)
	                cascade_light<=0;
	        else if(color_restore_receiver==1)//子控使用色彩还原时，分控对亮度不做处理
	        	cascade_light<=9'h100;
	        else
		        cascade_light<=mac_data+1;
		end
		
//*******************测试模块帧采样****************************//
always@(posedge sclk)
        test_vs_r<=test_vs;

always@(posedge sclk)
        if((test_vs_r==0 && test_vs==1) && (local_test_en==1'b1 || local_picture_en==1'b1))
                local_vs_negedge<=1;
        else
                local_vs_negedge<=0;
                
//*******************渐亮计数****************************//
always	@(posedge sclk)
        if(black==1'b1)
                start_light <= 8'h00;
        else if (light_on_protect == 1'b0)
                start_light <= 8'h80;
        else if (start_light[7] == 0 && (local_vs_negedge == 1'b1 || (vsout == 0 && zdec_vsout == 1)))
                start_light <= start_light + 1;
                
//*****************数据调整写控制***************//
mult_9X9  sys_adj_mult(
	.dataa(cascade_light), 		//9'h100
	.datab({1'h0,start_light}), 		//8'h80
	.result(sys_adj_result)); 	//16'h8000
	
mult_16_16  adj_r_mult(
	.dataa({7'h0,unit_r_adj}), 		//9'h100
	.datab(sys_adj_result[15:0]), 	//16'h8000	
	.result(adj_result_r));		//24'h800000

assign	r_adj_out = adj_result_r[23:8];

mult_16_16  adj_g_mult(
	.dataa({7'h0,unit_g_adj}), 		//9'h100
	.datab(sys_adj_result[15:0]), 	//16'h8000	
	.result(adj_result_g));		//24'h800000

assign	g_adj_out = adj_result_g[23:8];

mult_16_16  adj_b_mult(
	.dataa({7'h0,unit_b_adj}), 		//9'h100
	.datab(sys_adj_result[15:0]), 	//16'h8000	
	.result(adj_result_b));		//24'h800000

assign	b_adj_out = adj_result_b[23:8];

mult_16_16  adj_w_mult(
	.dataa({7'h0,unit_w_adj}), 		//9'h100
	.datab(sys_adj_result[15:0]), 	//16'h8000	
	.result(adj_result_w));		//24'h800000

assign	w_adj_out = adj_result_w[23:8];

always@(posedge sclk)
	unit_color_adj <={w_adj_out,b_adj_out,g_adj_out,r_adj_out};

/************************************************/
//		测试信号
/************************************************/
		
assign	tout=0;

endmodule		

